package encrypt

import (
	"crypto"
	"crypto/md5"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"golang.org/x/crypto/pkcs12"
	"io"
	"io/ioutil"
	"strconv"
	"strings"
)

/**
 * @Author admin
 * @Description //从pfx文件中读取公私密钥（需要安装golang.org/x/crypto/pkcs12）
 * @Date 0:51 2022/8/21
 * @Param
 * @return
 **/
func ReadFromPfx(pfxFile, password string) ([]byte, []byte) {
	buffer, err := ioutil.ReadFile(pfxFile)
	if err != nil {
		panic(err)
	}

	//privateKeyInterface, certificate, err := pkcs12.Decode(buffer, password)
	privateKeyInterface, _, err := pkcs12.Decode(buffer, password)
	if err != nil {
		panic(err)
	}

	privateKey := privateKeyInterface.(*rsa.PrivateKey)
	//publicKey := certificate.PublicKey.(*rsa.PublicKey)

	var (
		privateKeyBuffer []byte
		//publicKeyBuffer  []byte
	)
	privateKeyBuffer = x509.MarshalPKCS1PrivateKey(privateKey)
	//publicKeyBuffer = x509.MarshalPKCS1PublicKey(publicKey)
	return nil, privateKeyBuffer
}

/**
 * @Author admin
 * @Description //从crt中读取公钥
 * @Date 0:50 2022/8/21
 * @Param
 * @return
 **/
func ReadPublicKeyFromCrt(crtFile string) ([]byte, error) {
	buffer, err := ioutil.ReadFile(crtFile)
	if err != nil {
		return nil, err
	}
	certDERBlock, _ := pem.Decode(buffer)
	certificate, err := x509.ParseCertificate(certDERBlock.Bytes)
	if err != nil {
		return nil, err
	}
	publicKey := certificate.PublicKey.(*rsa.PublicKey)

	var publicKeyBuffer []byte
	publicKeyBuffer = x509.MarshalPKCS1PublicKey(publicKey)

	if err != nil {
		return nil, err
	}
	return publicKeyBuffer, nil
}

/**
 * @Author admin
 * @Description //解析key
 * @Date 0:50 2022/8/21
 * @Param
 * @return
 **/
func parsePkcsKey(buffer []byte, isPrivateKey bool) (interface{}, error) {
	var (
		err          error
		keyInterface interface{}
	)

	if isPrivateKey {
		keyInterface, err = x509.ParsePKCS1PrivateKey(buffer)
	} else {
		keyInterface, err = x509.ParsePKCS1PublicKey(buffer)
	}
	if err != nil {
		return nil, err
	}
	return keyInterface, nil
}

/**
 * @Author admin
 * @Description //
 * @Date 16:58 2022/8/21
 * @Param
 * @return
 **/
func Base64Encode(str string) string {
	message := base64.StdEncoding.EncodeToString([]byte(str))
	return strings.ReplaceAll(message, "[\\s*\t\n\r]", "")
}

/**
 * @Author admin
 * @Description //Md5Hex
 * @Date 16:59 2022/8/21
 * @Param
 * @return
 **/
func Md5Hex(src string) string {
	m := md5.New()
	m.Write([]byte(src))
	res := hex.EncodeToString(m.Sum(nil))
	return res
}

/**
 * @Author admin
 * @Description //RSA加密
 * @Date 0:50 2022/8/21
 * @Param
 * @return
 **/
func RsaEncrypt(value string, publicKey []byte) (string, error) {
	keyInterface, err := parsePkcsKey(publicKey, false)
	if err != nil {
		return "", err
	}
	rsaPublicKey := keyInterface.(*rsa.PublicKey)
	/*	name := "afadad"
		bName := []byte(name)
		hName := hex.EncodeToString(bName)
		fmt.Println(hName)  // e9a9ace4ba9ae58d97
		// 16进制字符串转回bytes类型
		bName, _ = hex.DecodeString(hName)*/
	if decodeString, err := hex.DecodeString(value); err == nil {
		if buffer, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, decodeString); err == nil {
			//以hex格式数值输出
			//encryptText := fmt.Sprintf("%x", buffer)
			return string(buffer), nil
		} else {
			fmt.Println(err)
		}
	}
	return "", err
}

/**
 * @Author admin
 * @Description //RSA解密
 * @Date 0:50 2022/8/21
 * @Param
 * @return
 **/
func RsaDecrypt(value string, privateKey []byte, usePKCS8 bool) (string, error) {
	//将hex格式数据转换为byte切片
	valueBytes := []byte(value)
	var buffer = make([]byte, len(valueBytes)/2)
	for i := 0; i < len(buffer); i++ {
		b, err := strconv.ParseInt(value[i*2:i*2+2], 16, 10)
		if err != nil {
			return "", err
		}
		buffer[i] = byte(b)
	}

	keyInterface, err := parsePkcsKey(privateKey, true)
	if err != nil {
		return "", err
	}
	key := keyInterface.(*rsa.PrivateKey)
	buffer, err = rsa.DecryptPKCS1v15(rand.Reader, key, buffer)
	return string(buffer), nil
}

/**
 * @Author admin
 * @Description //RSA签名
 * @Date 0:50 2022/8/21
 * @Param
 * @return
 **/
func Sign(value string, privateKey []byte, hash crypto.Hash) (string, error) {
	keyInterface, err := parsePkcsKey(privateKey, true)
	if err != nil {
		return "", err
	}
	key := keyInterface.(*rsa.PrivateKey)

	var _hash = hash.New()
	if _, err := io.WriteString(_hash, value); err != nil {
		return "", err
	}

	hashed := _hash.Sum(nil)
	result, err := rsa.SignPKCS1v15(rand.Reader, key, hash, hashed)
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(result), nil
}

/**
 * @Author admin
 * @Description //签名
 * @Date 0:49 2022/8/21
 * @Param
 * @return
 **/
func RsaSign(signContent string, privateKey []byte, hash crypto.Hash) string {
	shaNew := hash.New()
	shaNew.Write([]byte(signContent))
	hashed := shaNew.Sum(nil)
	keyInterface, err := parsePkcsKey(privateKey, true)
	if err != nil {
		return ""
	}
	key := keyInterface.(*rsa.PrivateKey)

	signature, err := rsa.SignPKCS1v15(rand.Reader, key, hash, hashed)
	if err != nil {
		panic(err)
	}
	return hex.EncodeToString(signature)
}

/**
 * @Author admin
 * @Description //RSA验证签名
 * @Date 0:49 2022/8/21
 * @Param
 * @return
 **/
func Verify(value string, publicKey []byte, signature string, hash crypto.Hash) bool {
	decodeString, err := hex.DecodeString(signature)
	if err != nil {
		return false
	}
	keyInterface, err := parsePkcsKey(publicKey, false)
	if err != nil {
		return false
	}

	key := keyInterface.(*rsa.PublicKey)

	var _hash = hash.New()
	if _, err := io.WriteString(_hash, value); err != nil {
		return false
	}

	hashed := _hash.Sum(nil)
	if err := rsa.VerifyPKCS1v15(key, hash, hashed, decodeString); err != nil {
		return false
	}
	return true

}
